#pragma once
#if LIT_OGRE_SUPPORT

#ifndef __LIT__APPLICATION__SETINGS__HH__
#define __LIT__APPLICATION__SETINGS__HH__

#include <LitPrerequisites.h>
#include <LitString.h>
#include <LitMetaObject.h>

namespace Lit
{
	enum ApplicationSettingsGroup
	{
		ASG_GENERAL,
		ASG_OGRE,
		ASG_INPUT
	};
	enum ApplicationSettingsConfigLevel
	{
		ASCL_LOWEST,
		ASCL_LOW,
		ASCL_MEDIUM,
		ASCL_HIGH,
		ASCL_HIGHER,
		ASCL_HIGHEST
	};

	class LIT_API ApplicationSettings : public MetaObject, public MetaObjectSerialiser
	{
	protected:
	public:
		ApplicationSettings(void);
		ApplicationSettings( const ApplicationSettings& rk );
		~ApplicationSettings(void);

		typedef std::unordered_map<String, String> RenderSystemConfigMap;

		static String translateConfigLevel(ApplicationSettingsConfigLevel lvl);

		
		template<typename T>
		T getOgreProperty( const String &prop, const T &def_val = T() )
		{
			String n(translateGroup(ASG_OGRE));
			return MetaObject::hasGroup(n)?MetaObject::getGroup(n).getProperty<T>(prop, def_val):def_val;
		}
		template<typename T>
		T getOgreProperty( const String &prop, const T &def_val = T() ) const
		{
			String n(translateGroup(ASG_OGRE));
			return MetaObject::hasGroup(n)?MetaObject::getGroup(n).getProperty<T>(prop, def_val):def_val;
		}
		
		bool hasOgreProperty( const String &name ) const{
			String n(translateGroup(ASG_OGRE));
			return MetaObject::hasGroup(n)?MetaObject::getGroup(n).hasKey(name):false;
		}
		void setOgreProperty( const String &name , const String& value )
		{
			String n(translateGroup(ASG_OGRE));
			if( !MetaObject::hasGroup(n) )
				setGroup( MetaGroup( this, n ) );
			MetaObject::getGroup(n).setProperty( name, value );
		}

		MetaGroup& getRenderSystemConfig( ApplicationSettingsConfigLevel lvl );
		const MetaGroup& getRenderSystemConfig( ApplicationSettingsConfigLevel lvl ) const;
		
		bool hasRenderSystemConfig(ApplicationSettingsConfigLevel lvl) const;
		void setRenderSystemConfig( ApplicationSettingsConfigLevel lvl, const MetaGroup& g );
		MetaGroup& createRenderSystemConfig( ApplicationSettingsConfigLevel lvl );
		template<typename T>
		void setRenderSystemProperty( ApplicationSettingsConfigLevel lvl, const String &name, const T & val = T() )
		{
			getRenderSystemConfig( lvl ).setProperty("RenderSystem."+name, String(val).str());
		}
		template<typename T>
		T getRenderSystemProperty( ApplicationSettingsConfigLevel lvl, const String &name, const T & def_val = T() )
		{
			return getRenderSystemConfig( lvl ).getProperty<T>("RenderSystem."+name, def_val);
		}
		String getRenderSystemConfigName(ApplicationSettingsConfigLevel lvl) const;
		String getRenderSystemName( const String &def_name) const;
		void setRenderSystemName( const String &name );
		
		static ApplicationSettings DEFAULTS();

		void setRenderSystemProperties( 
			ApplicationSettingsConfigLevel lvl, 
			unsigned short fsaa,
			bool fullscreen,
			unsigned short width, unsigned short height,
			unsigned short bpp, 
			bool vsync,
			unsigned short refresh_rate
		);


		bool hasGroup( ApplicationSettingsGroup grp ) const;
		MetaGroup& getGroup( ApplicationSettingsGroup grp );
		const MetaGroup& getGroup( ApplicationSettingsGroup grp ) const;

		static String translateGroup( ApplicationSettingsGroup grp );

		void load( const String &filename );
		void save( const String &filename );
	};
};

#endif

#endif